#include "win32_window.h"

namespace test_application {

bool Win32Window::keys[256];

Win32Window::Win32Window(ApplicationState & state) : WindowWrapper(state) {
    WNDCLASS	wc;							// Windows Class Structure

    instance_handle_	= GetModuleHandle(NULL);			// Grab An Instance For Our Window
    wc.style		    = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;		// Redraw On Move, And Own DC For Window
    wc.lpfnWndProc		= (WNDPROC) Win32Window::MessageHandler;	
    wc.cbClsExtra		= 0;						    // No Extra Window Data
    wc.cbWndExtra		= 0;						    // No Extra Window Data
    wc.hInstance		= instance_handle_;					// Set The Instance
    wc.hIcon		    = LoadIcon(NULL, IDI_WINLOGO);	// Load a default icon
    wc.hCursor		    = LoadCursor(NULL, IDC_ARROW);	// Load a default cursor
    wc.hbrBackground	= (HBRUSH)GetStockObject(BLACK_BRUSH);  // black background brush
    wc.lpszMenuName		= NULL;						    // No Menu
    wc.lpszClassName	= TEXT("Win32Window");		    
    
    RegisterClass(&wc);
}

int Win32Window::DoEvents() {
    MSG msg;
    if(PeekMessage(&msg, window_handle_, 0,0, PM_REMOVE)) {
        if(msg.message == WM_QUIT) {
            Close();
        }
        else {
			TranslateMessage(&msg);				// Translate The Message
			DispatchMessage(&msg);				// Dispatch The Message
		}
    }

    if (keys[VK_ESCAPE]) {
        Close();
    }
    if (keys[VK_F1]) {					// Is F1 Being Pressed?
		keys[VK_F1]=FALSE;				// If So Make Key FALSE
		if(state_.test(APP_FULLSCREEN))
            ToWindowed();
        else ToFullscreen();
	}
    

    return base::OK_OK;

    
}
 
LRESULT	CALLBACK Win32Window::MessageHandler(HWND window, UINT msg, WPARAM wparam, LPARAM lparam) {
	switch (msg) {
        case WM_CLOSE:
            Kernel::KillAllTasks();
            return 0;
        case WM_DESTROY :				// Did We Receive A Close Message?
			PostQuitMessage(0);						// Send A Quit Message
			return 0;								// Jump Back	
        case WM_PAINT: 
            InvalidateRect(window, NULL, false);
            return 0;
        case WM_KEYDOWN:						// Is A Key Being Held Down?		
            keys[wparam] = true;
            return 0;
        case WM_KEYUP:
            keys[wparam] = false;
            return 0;
	}

    //UpdateWindow(window);
	// Pass All Unhandled Messages To DefWindowProc
	return DefWindowProc(window,msg,wparam,lparam);
}

int Win32Window::OnInitialize() {


    bool fullscreen = state_.test(APP_FULLSCREEN);

    DWORD		extended_style;					// Window Extended Style
    DWORD		style;                          //Window Style

    if(fullscreen) {
        extended_style = WS_EX_APPWINDOW;				
        style = WS_POPUP;
    } else {
        extended_style = WS_EX_APPWINDOW | WS_EX_WINDOWEDGE;   
	    style = WS_OVERLAPPEDWINDOW;	
    }

    if(!state_.test(APP_HIDDEN))
    {        
        style |= WS_VISIBLE;
        if(fullscreen)
            style |= WS_MAXIMIZE;
    }
    RECT window_rect;
    window_rect.left=(long)0;			                // Set Left Value To 0
	window_rect.top=(long)0;			                // Set Top Value To 0
    window_rect.right=(long)properties_.GetWidth();		// Set Right Value To Requested Width
    window_rect.bottom=(long)properties_.GetHeight();   // Set Bottom Value To Requested Height

    // Adjust Window To True Requested Size
    AdjustWindowRectEx(&window_rect, style, FALSE, extended_style);

    HWND to_delete = window_handle_;
    window_handle_ = CreateWindowExA( extended_style,		// Extended Style For The Window
				    "Win32Window",				        // Class Name
				    properties_.GetTitle().c_str(),	    // Window Title
				    WS_CLIPSIBLINGS |			        // Required Window Style
				    WS_CLIPCHILDREN |			        // Required Window Style
				    style,				                // Selected Window Style
                    properties_.GetPositionX(), 
                    properties_.GetPositionY(),					
                    window_rect.right - window_rect.left,   // Calculate Adjusted Window Width
				    window_rect.bottom - window_rect.top,	// Calculate Adjusted Window Height				NULL,					// No Parent Window
				    NULL,					// No Parent Window
				    NULL,					// No Menu
				    instance_handle_,		// Instance
				    NULL);					// Don't Pass Anything To WM_CREATE

    if(!window_handle_) {
        window_handle_ = to_delete;
        return base::ER_ERROR;
    }
    
    SetForegroundWindow(window_handle_);
    DestroyWindow(to_delete);

    return base::OK_TRUE;
}

int Win32Window::OnClose() {
    if( DestroyWindow(window_handle_) )
        return base::OK_TRUE;
    else return base::OK_FALSE;
}
 

int Win32Window::OnResize(const long &width, const long &height) {
  RECT client_rect, window_rect;
  long dx, dy;  
  GetClientRect(window_handle_, &client_rect);
  GetWindowRect(window_handle_, &window_rect);
  dx = (window_rect.right - window_rect.left) - client_rect.right;
  dy = (window_rect.bottom - window_rect.top) - client_rect.bottom;
  MoveWindow(window_handle_,window_rect.left, window_rect.top, width + dx, height + dy, TRUE);
  return base::OK_OK;
}



}